﻿using System.Drawing;

namespace RoboRallyAPI
{
	/// <summary>
	/// Each AI must implement this interface .
	/// </summary>
	public interface IPlayer
	{

		/// <summary>
		/// The name of the player.
		/// </summary>
		string Name { get; }

		/// <summary>
		/// The avatar of the player. Must be 32 x 32.
		/// </summary>
		Image Avatar { get; }

		/// <summary>
		/// Called when your robot must be placed on the board. This is called at the start of the game and each time your robot dies.
		/// </summary>
		/// <param name="map">The game map. There will be no units on this map.</param>
		/// <param name="you">Your player object.</param>
		/// <param name="robotStart">The position(s) on the map where you can place your robot. This will be a single point unless another robot is on your archive point.</param>
		/// <returns>Where to place your unit (location and direction.</returns>
		PlayerSetup Setup(GameMap map, Player you, Point[] robotStart);

		/// <summary>
		/// Called each time the system needs another turn. If you do not return a valid turn, the game will randomly move one of your units.
		/// This call must return in under 1 second. If it has not returned in 1 second the call will be aborted and a random move will be assigned.
		/// </summary>
		/// <param name="map">The game map with all units on it.</param>
		/// <param name="you">Your player object. This is created for each call.</param>
		/// <param name="allPlayers">All players including you. This is created for each call.</param>
		/// <param name="cards">The cards you get to pick from. This does not include locked cards.</param>
		/// <returns>Your requested turn.</returns>
		PlayerTurn Turn(GameMap map, Player you, Player[] allPlayers, Card[] cards);
	}

	/// <summary>
	/// Used to return the requested start position for a player.
	/// </summary>
	public class PlayerSetup
	{
		public PlayerSetup(Point position, MapSquare.DIRECTION direction)
		{
			Position = position;
			Direction = direction;
		}

		public Point Position { get; private set; }
		public MapSquare.DIRECTION Direction { get; private set; }
	}

	/// <summary>
	/// A requested move for a player's turn.
	/// </summary>
	public class PlayerTurn
	{

		/// <summary>
		/// Why a turn was not accepted. 
		/// </summary>
		public enum FAIL_REASON
		{
			/// <summary>
			/// Turn was successful.
			/// </summary>
			SUCCESS,

			/// <summary>
			/// The Turn call timed out.
			/// </summary>
			TIMEOUT,

			/// <summary>
			/// The Turn call threw an exception.
			/// </summary>
			EXCEPTION,

			/// <summary>
			/// The Turn call provided an invalid turn.
			/// </summary>
			INVALID
		};

		/// <summary>
		/// Return your turn. If you have locked cards will only use the first N (unlocked) cards returned. If you do not return 
		/// enough cards, random cards will be assigned. Locked cards are the last N cards from the previous turn.
		/// </summary>
		/// <param name="cards">Your unlocked cards.</param>
		/// <param name="powerDown">true if power down at the end of this turn.</param>
		public PlayerTurn(Card[] cards, bool powerDown)
		{
			Cards = cards ?? new Card[0];
			IsPowerDown = powerDown;
		}

		/// <summary>
		/// The cards requested for the upcoming turn. If your Damage is greater than 4 then not all 5 of these will be used, but you
		/// may return 5. The extras will be ignored.
		/// </summary>
		public Card[] Cards { get; private set; }

		/// <summary>
		/// Return true to power down at the end of the upcoming turn. You also need to return Cards because the power down occurs
		/// AFTER this turn!
		/// </summary>
		public bool IsPowerDown { get; private set; }
	}
}
